#include "test.h"


static int test_iriref()
{
    char *uri1_data = "http://example.org/term#12345";
    char *uri2_data = "ns1:12345";
    char *uri3_data = "ns2:12345";

    LSUP_NSMap *nsm1 = LSUP_nsmap_new();
    LSUP_nsmap_add (nsm1, "ns1", "http://example.org/term#");

    LSUP_NSMap *nsm2 = LSUP_nsmap_new();
    LSUP_nsmap_add (nsm2, "ns2", "http://example.org/term#");

    LSUP_Term *uri1 = LSUP_iriref_new (uri1_data, NULL);
    ASSERT (uri1, "IRI is NULL!");
    ASSERT (LSUP_iriref_nsm (uri1) == NULL, "Wrong NSMap!");
    char *pfx = LSUP_iriref_prefix (uri1);
    char *path = LSUP_iriref_path (uri1);
    char *frag = LSUP_iriref_frag (uri1);
    EXPECT_STR_EQ (pfx, "http://example.org");
    EXPECT_STR_EQ (path, "/term#12345");
    EXPECT_STR_EQ (frag, "12345");
    free (pfx);
    free (path);
    free (frag);

    LSUP_Term *uri2 = LSUP_iriref_new (uri2_data, nsm1);
    ASSERT (uri2, "IRI is NULL!");
    ASSERT (LSUP_iriref_nsm (uri2) == nsm1, "Wrong NSMap!");

    LSUP_Term *uri3 = LSUP_iriref_new (uri3_data, nsm2);
    ASSERT (uri3, "IRI is NULL!");
    ASSERT (LSUP_iriref_nsm (uri3) == nsm2, "Wrong NSMap!");

    LSUP_Term *uri4 = LSUP_iriref_new (NULL, NULL);
    ASSERT (uri4, "IRI is NULL!");

    LSUP_Term *uri5 = LSUP_iriref_new (NULL, NULL);
    ASSERT (uri5, "IRI is NULL!");

    EXPECT_INT_EQ (uri1->type, LSUP_TERM_IRIREF);
    EXPECT_INT_EQ (uri2->type, LSUP_TERM_NS_IRIREF);
    EXPECT_INT_EQ (uri3->type, LSUP_TERM_NS_IRIREF);
    EXPECT_INT_EQ (uri4->type, LSUP_TERM_IRIREF);
    EXPECT_INT_EQ (uri5->type, LSUP_TERM_IRIREF);

    ASSERT (LSUP_term_equals (uri1, uri2), "IRIs don't match!");
    ASSERT (LSUP_term_equals (uri2, uri3), "IRIs don't match!");
    ASSERT (!LSUP_term_equals (uri3, uri4), "IRIs shouldn't match!");
    ASSERT (!LSUP_term_equals (uri4, uri5), "IRIs shouldn't match!");

    LSUP_term_free (uri1);
    LSUP_term_free (uri2);
    LSUP_term_free (uri3);
    LSUP_term_free (uri4);
    LSUP_term_free (uri5);
    LSUP_nsmap_free (nsm1);
    LSUP_nsmap_free (nsm2);

    return 0;
}


static int test_iriref_abs_rel()
{
    LSUP_NSMap *nsm1 = LSUP_nsmap_new();
    LSUP_nsmap_add (nsm1, "ns1", "http://example.org/res/");

    LSUP_Term *root1 = LSUP_iriref_new ("http://example.org/res/", NULL);
    LSUP_Term *root2 = LSUP_iriref_new ("urn:id:", NULL);

    LSUP_Term *rel_iri1 = LSUP_iriref_new ("http://anotherex.net/res/25", NULL);
    LSUP_Term *rel_iri2 = LSUP_iriref_new ("/admin/32", NULL);
    LSUP_Term *rel_iri3 = LSUP_iriref_new ("45/678", NULL);

    LSUP_Term *abs_iri1 = LSUP_iriref_absolute (root1, rel_iri1);
    LSUP_Term *abs_iri2 = LSUP_iriref_absolute (root1, rel_iri2);
    LSUP_Term *abs_iri3 = LSUP_iriref_absolute (root1, rel_iri3);

    EXPECT_STR_EQ (abs_iri1->data, rel_iri1->data);
    EXPECT_STR_EQ (abs_iri2->data, "http://example.org/admin/32");
    EXPECT_STR_EQ (abs_iri3->data, "http://example.org/res/45/678");

    LSUP_Term *rel_iri1a = LSUP_iriref_relative (root1, abs_iri1);
    LSUP_Term *rel_iri2a = LSUP_iriref_relative (root1, abs_iri2);
    LSUP_Term *rel_iri3a = LSUP_iriref_relative (root1, abs_iri3);

    EXPECT_STR_EQ (rel_iri1a->data, rel_iri1->data);
    EXPECT_STR_EQ (rel_iri2a->data, abs_iri2->data);
    EXPECT_STR_EQ (rel_iri3a->data, "45/678");

    LSUP_term_free (root1);
    LSUP_term_free (root2);
    LSUP_term_free (rel_iri1);
    LSUP_term_free (rel_iri2);
    LSUP_term_free (rel_iri3);
    LSUP_term_free (abs_iri1);
    LSUP_term_free (abs_iri2);
    LSUP_term_free (abs_iri3);
    LSUP_term_free (rel_iri1a);
    LSUP_term_free (rel_iri2a);
    LSUP_term_free (rel_iri3a);
    LSUP_nsmap_free (nsm1);

    return 0;
}


static int test_literal()
{
    char *data = "hello";
    char *datatype = "urn:my:datatype";
    char *lang = "en-US";

    LSUP_Term *lit1 = LSUP_literal_new (data, LSUP_iriref_new (datatype, NULL));
    EXPECT_INT_EQ (lit1->type, LSUP_TERM_LITERAL);
    EXPECT_STR_EQ (lit1->data, data);
    EXPECT_STR_EQ (lit1->datatype->data, datatype);

    LSUP_Term *lit2 = LSUP_literal_new (data, LSUP_default_datatype);
    EXPECT_INT_EQ (lit2->type, LSUP_TERM_LITERAL);
    EXPECT_STR_EQ (lit2->data, data);
    EXPECT_STR_EQ (lit2->datatype->data, DEFAULT_DTYPE);

    LSUP_Term *lit3 = LSUP_literal_new (data, NULL);
    EXPECT_INT_EQ (lit3->type, LSUP_TERM_LITERAL);
    EXPECT_STR_EQ (lit3->data, data);
    EXPECT_STR_EQ (lit3->datatype->data, DEFAULT_DTYPE);

    ASSERT (lit1->datatype != lit2->datatype, "Wrong data type match!");
    ASSERT (lit2->datatype == lit3->datatype, "Data type mismatch!");

    ASSERT (!LSUP_term_equals (lit1, lit2), "Wrong term match!");
    ASSERT (LSUP_term_equals (lit2, lit3), "Term mismatch!");

    LSUP_Term *lt_lit1 = LSUP_lt_literal_new (data, lang);
    EXPECT_INT_EQ (lt_lit1->type, LSUP_TERM_LT_LITERAL);
    EXPECT_STR_EQ (lt_lit1->data, data);
    EXPECT_STR_EQ (lt_lit1->lang, lang);

    // LT-literal without lang is a normal string literal.
    LSUP_Term *lt_lit2 = LSUP_lt_literal_new (data, NULL);
    EXPECT_INT_EQ (lt_lit2->type, LSUP_TERM_LITERAL);
    EXPECT_STR_EQ (lt_lit2->data, data);

    ASSERT (LSUP_term_equals (lt_lit2, lit2), "Term mismatch!");
    EXPECT_STR_EQ (lt_lit2->datatype->data, DEFAULT_DTYPE);

    LSUP_term_free (lit1);
    LSUP_term_free (lit2);
    LSUP_term_free (lit3);
    LSUP_term_free (lt_lit1);
    LSUP_term_free (lt_lit2);

    return 0;
}

static int test_term_copy()
{
    LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org", NULL);
    LSUP_Term *lit1 = LSUP_literal_new ("hello", NULL);
    LSUP_Term *tlit1 = LSUP_literal_new (
            "hello", LSUP_iriref_new ("urn:mydatatype:string", NULL));
    LSUP_Term *llit1 = LSUP_lt_literal_new ("hello", "en-US");

    LSUP_Term *uri2 = LSUP_term_copy (uri1);
    LSUP_Term *lit2 = LSUP_term_copy (lit1);
    LSUP_Term *tlit2 = LSUP_term_copy (tlit1);
    LSUP_Term *llit2 = LSUP_term_copy (llit1);

    ASSERT (LSUP_term_equals (uri1, uri2), "Term mismatch!");
    ASSERT (LSUP_term_equals (lit1, lit2), "Term mismatch!");
    ASSERT (LSUP_term_equals (tlit1, tlit2), "Term mismatch!");
    ASSERT (LSUP_term_equals (llit1, llit2), "Term mismatch!");

    LSUP_term_free (uri1);
    LSUP_term_free (uri2);
    LSUP_term_free (lit1);
    LSUP_term_free (lit2);
    LSUP_term_free (tlit1);
    LSUP_term_free (tlit2);
    LSUP_term_free (llit1);
    LSUP_term_free (llit2);

    return 0;
}

static int test_term_serialize_deserialize()
{
    LSUP_Term *uri = LSUP_iriref_new ("http://hello.org", NULL);
    LSUP_Term *lit = LSUP_literal_new ("hello", NULL);
    LSUP_Term *tlit = LSUP_literal_new (
            "hello", LSUP_iriref_new ("urn:mydatatype:string", NULL));
    LSUP_Term *llit = LSUP_lt_literal_new ("hello", "en-US");

    LSUP_Buffer *sterm;
    LSUP_Term *dsterm;

    sterm = LSUP_term_serialize (uri);
    ASSERT (sterm != NULL, "Error serializing term!");
    //log_info ("%s", "Serialized URI: ");
    //LSUP_buffer_print (sterm);
    //log_info ("%s", "\n");
    dsterm = LSUP_term_new_from_buffer (sterm);
    ASSERT (dsterm != NULL, "Error deserializing term!");
    ASSERT (LSUP_term_equals (dsterm, uri), "URI serialization error!");
    LSUP_term_free (uri);
    LSUP_buffer_free (sterm);
    LSUP_term_free (dsterm);

    sterm = LSUP_term_serialize (lit);
    ASSERT (sterm != NULL, "Error serializing term!");
    //log_info ("%s", "Serialized literal: ");
    //LSUP_buffer_print (sterm);
    //log_info ("%s", "\n");
    dsterm = LSUP_term_new_from_buffer (sterm);
    ASSERT (dsterm != NULL, "Error deserializing term!");
    ASSERT (LSUP_term_equals (dsterm, lit), "lit serialization error!");
    LSUP_term_free (lit);
    LSUP_buffer_free (sterm);
    LSUP_term_free (dsterm);

    sterm = LSUP_term_serialize (tlit);
    ASSERT (sterm != NULL, "Error serializing term!");
    //log_info ("%s", "Serialized typed literal: ");
    //LSUP_buffer_print (sterm);
    //log_info ("%s", "\n");
    dsterm = LSUP_term_new_from_buffer (sterm);
    ASSERT (dsterm != NULL, "Error deserializing term!");
    ASSERT (LSUP_term_equals (dsterm, tlit), "tlit serialization error!");
    LSUP_term_free (tlit);
    LSUP_buffer_free (sterm);
    LSUP_term_free (dsterm);

    sterm = LSUP_term_serialize (llit);
    ASSERT (sterm != NULL, "Error serializing term!");
    //log_info ("%s", "Serialized typed and language-tagged URI: ");
    //LSUP_buffer_print (sterm);
    //log_info ("%s", "\n");
    dsterm = LSUP_term_new_from_buffer (sterm);
    ASSERT (dsterm != NULL, "Error deserializing term!");
    ASSERT (LSUP_term_equals (dsterm, llit), "URI serialization error!");
    LSUP_term_free (llit);
    LSUP_buffer_free (sterm);
    LSUP_term_free (dsterm);

    return 0;
}


static int test_term_to_key()
{
    LSUP_NSMap *nsm = LSUP_nsmap_new();
    LSUP_nsmap_add (nsm, "ns1", "http://hello.org/term#");

    LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org/term#bye", NULL);
    LSUP_Term *uri2 = LSUP_iriref_new ("ns1:bye", nsm);
    LSUP_Term *lit = LSUP_literal_new ("hello", NULL);
    LSUP_Term *tlit = LSUP_literal_new ("hello", LSUP_default_datatype);
    LSUP_Term *llit1 = LSUP_lt_literal_new ("hello", "en-US");
    LSUP_Term *llit2 = LSUP_lt_literal_new ("hello", "en-GB");
    LSUP_Term *llit3 = LSUP_lt_literal_new ("hello", NULL);

    LSUP_Key uri1_key = LSUP_term_hash (uri1);
    LSUP_Key uri2_key = LSUP_term_hash (uri2);
    LSUP_Key lit_key = LSUP_term_hash (lit);
    LSUP_Key tlit_key = LSUP_term_hash (tlit);
    LSUP_Key llit1_key = LSUP_term_hash (llit1);
    LSUP_Key llit2_key = LSUP_term_hash (llit2);
    LSUP_Key llit3_key = LSUP_term_hash (llit3);

    ASSERT (uri1_key == uri2_key, "URI keys differ!");
    ASSERT (uri1_key != lit_key, "URI key conflict!");
    ASSERT (lit_key == tlit_key, "URI keys differ!");
    ASSERT (lit_key != llit1_key, "URI key conflict!");
    ASSERT (tlit_key != llit1_key, "URI key conflict!");
    ASSERT (llit1_key != llit2_key, "URI key conflict!");
    ASSERT (tlit_key == llit3_key, "URI keys differ!");

    LSUP_term_free (uri1);
    LSUP_term_free (uri2);
    LSUP_term_free (lit);
    LSUP_term_free (tlit);
    LSUP_term_free (llit1);
    LSUP_term_free (llit2);
    LSUP_term_free (llit3);
    LSUP_nsmap_free (nsm);

    return 0;
}


int term_tests() {
    RUN (test_iriref);
    RUN (test_iriref_abs_rel);
    RUN (test_literal);
    RUN (test_term_copy);
    RUN (test_term_serialize_deserialize);
    RUN (test_term_to_key);

    return 0;
}

